package cc.xsubj.trading.inventory;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.newdawn.slick.geom.Rectangle;

import cc.xsubj.trading.entity.InventoryItem;
import cc.xsubj.trading.exceptions.NotEnoughItemsException;
import cc.xsubj.trading.world.InventoryWorld;

public class Inventory {
	private List<ItemStack> items;
	
	private static Inventory playerInventory = load(null, true);
	//TODO: Replace npcInventory with a map from NPC name to Inventory
	private static Inventory npcInventory = load(null, false);
	
	private boolean isPlayerInventory;
	
	private static Rectangle playerInventoryBounds;
	private static Rectangle npcInventoryBounds;
	
	private Map<ItemType, Integer> willBuyPrices;
	private Map<ItemType, Integer> willSellPrices;
	
	private int gold;
	
	static
	{
	    playerInventoryBounds = new Rectangle(24, 24, 24*4, 24*10);
	    npcInventoryBounds = new Rectangle(24+24*4+24*2, 24, 24*4, 24*10);
	}
	
	private Inventory()
	{
		this(false);
	}
	
	private Inventory(boolean isPlayerInventory)
	{
		items = new ArrayList<ItemStack>();
		for(int i = 0; i < InventoryGrid.defaultGridWidth*InventoryGrid.defaultGridHeight; i++)
		{
		    items.add(null);
		}
		this.isPlayerInventory = isPlayerInventory;
		
		willBuyPrices = new HashMap<ItemType, Integer>();
		willSellPrices = new HashMap<ItemType, Integer>();
		
	}
	
	public static Inventory load(InputStream in, boolean isPlayerInventory)
	{
		//TODO: Implement loading from InputStream
		Inventory inv = new Inventory(isPlayerInventory);
		inv.addItem(new ItemStack(0, 5));
		inv.addItem(new ItemStack(1, 3));
		inv.gold = 1000;
		
		inv.willBuyPrices.put(ItemRegistry.getItemByName("Gold Coin"), 50);
		inv.willBuyPrices.put(ItemRegistry.getItemByName("Apple"), 1);
		
		inv.willSellPrices.put(ItemRegistry.getItemByName("Gold Coin"), 200);
		inv.willSellPrices.put(ItemRegistry.getItemByName("Apple"), 2);
		
		return inv;
	}
	
	
	public static Inventory getPlayerInventory()
	{
		return playerInventory;
	}
	
	public static Inventory getNPCInventory(String name)
	{
		return npcInventory;
	}
	
	public void removeItem(ItemStack item)
	{
		int index = items.lastIndexOf(item);
		if(index != -1)
		    items.set(index, null);
	}
	
	public int addItem(ItemStack item)
	{
	    //Inserts an ItemStack and returns the index it was inserted at.
	    //Returns >=0 if item was added, else -1.
		for (int i = 0; i < items.size(); i++)
		{
		    if (items.get(i) == null)
		    {
		        items.set(i, item);
		        System.out.println("Added " + item.getName() + " into slot " + i);
		        return i;
		    }
		}
		
		return -1;
	}
	
	public void insertItem(ItemStack item, int index)
	{
	    System.out.println("Inserted " + item.getName() + " into slot " + index);
	    items.set(index, item);
	}
	
	public void addItemsToInventoryWorld(InventoryWorld world, InventoryGrid grid)
	{
	    for (int i = 0; i < items.size(); i++)
	    {
	        ItemStack item = items.get(i);
	        if (item != null)
	        {
	            InventorySlot slot = grid.getSlots().get(i);
	            InventoryItem itemView = new InventoryItem(slot.getBounds().getX(), slot.getBounds().getY(), item);
	            if(isPlayerInventory)
	                itemView.setInPlayerInventory(true);
	            world.add(itemView);
	            itemView.slot = slot;
	        }
	    }
	}
	
	public boolean withdraw(int amount)
	{
	    // Withdraws amount gold if amount is available and returns true, else does nothing and returns false.
	    if (amount > gold)
	        return false;
        gold -= amount;
        return true;
	}
	
	public void deposit(int amount)
	{
	    gold += amount;
	}
	
	public int getGold()
	{
	    return gold;
	}

    public int getWillSellPrice(ItemType type)
    {
        Integer price = willSellPrices.get(type);
        return (price == null)? type.value * 2 : price;
    }

    public int getWillBuyPrice(ItemType type)
    {
        Integer price = willBuyPrices.get(type);
        return (price == null)? type.value / 2 : price;
    }
}
